<script setup>
import { ref, onMounted, getCurrentInstance, nextTick, watch } from 'vue'
import { listCategories, updateCategories } from '@/api/manage/categories'
import { listVariables } from '@/api/manage/variables'
import { handleTree } from '@/utils/ruoyi'
import { ElMessageBox } from 'element-plus'

const { proxy } = getCurrentInstance() || {};

const categoriesTree = ref([])
const loading = ref(false)
const treeProps = {
  label: 'name',
  children: 'children',
}

// 变量相关
const variables = ref([])
// variableMap: key 为 description+unit，value 为 variable
const variableMap = ref({})

// 公式弹窗相关
const formulaDialogVisible = ref(false)
const currentNode = ref(null)

// 消费税
const consumptionCumpte = ref('')
const consumptionDatatype = ref('')

// 增值税
const valueAddedRate = ref({ general: '', small: '' })
const valueAddedCumpte = ref({ general: '', small: '' })
const valueAddedDatatype = ref({ general: '', small: '' })

// 记录当前聚焦的输入框ID
const focusedTextareaId = ref('')

// 监听输入框聚焦事件
function onTextareaFocus(e) {
  focusedTextareaId.value = e.target.id
}

// 单击变量插入
function onVariableClick(variable) {
  // 找到当前聚焦的输入框
  const id = focusedTextareaId.value
  if (!id) {
    proxy.$modal.msgWarning('请先点击公式输入框再插入变量')
    return
  }
  // 获取输入框DOM
  const textarea = document.getElementById(id)
  if (!textarea) return
  // 判断同名变量数量
  const sameDescCount = variables.value.filter(v => v.description === variable.description).length
  let text = ''
  if (sameDescCount === 1) {
    text = variable.description
  } else {
    text = variable.description + (variable.unit ? `(${variable.unit})` : '')
  }
  const start = textarea.selectionStart
  const end = textarea.selectionEnd
  const currentValue = textarea.value
  const newValue = currentValue.substring(0, start) + text + currentValue.substring(end)

  // 更新对应的v-model
  if (id === 'consumption-cumpte') {
    consumptionCumpte.value = newValue
  } else if (id === 'vat-general-cumpte') {
    valueAddedCumpte.value.general = newValue
  } else if (id === 'vat-small-cumpte') {
    valueAddedCumpte.value.small = newValue
  }
  nextTick(() => {
    textarea.focus()
    textarea.selectionStart = textarea.selectionEnd = start + text.length
  })
}

function getCategoriesTree() {
  loading.value = true
  listCategories().then(res => {
    const treeFn = proxy?.handleTree || handleTree
    categoriesTree.value = treeFn(res.data, 'id', 'parentId')
    loading.value = false
  })
}

function getVariables() {
  listVariables().then(res => {
    variables.value = res.rows || res.data || []
    variableMap.value = {}
    variables.value.forEach(v => {
      // key: description + (unit ? '(' + unit + ')' : '')
      const key = v.description + (v.unit ? `(${v.unit})` : '')
      variableMap.value[key] = v.variable
    })
  })
}

function safeParse(str) {
  if (!str || !str.startsWith('{') || !str.endsWith('}')) {
    return {}
  }
  try {
    // Use Function constructor for safer parsing of object-like strings
    return new Function('return ' + str)()
  } catch (e) {
    console.error('Failed to parse formula string:', str, e)
    return {}
  }
}

function isLeaf(node) {
  return !node.children || node.children.length === 0
}

function handleNodeClick(data, node) {
  if (isLeaf(data)) {
    currentNode.value = data
    // 消费税
    consumptionCumpte.value = data.consumptionCumpte || ''
    consumptionDatatype.value = data.consumptionDataType || ''

    // 增值税
    const rate = safeParse(data.valueAddedRate)
    const cumpte = safeParse(data.valueAddedCumpte)
    const datatype = safeParse(data.valueAddedDatatype)
    valueAddedRate.value = {
      general: rate['一般纳税人'] || '',
      small: rate['小规模纳税人'] || '',
    }
    valueAddedCumpte.value = {
      general: cumpte['一般纳税人'] || '',
      small: cumpte['小规模纳税人'] || '',
    }
    valueAddedDatatype.value = {
      general: datatype['一般纳税人'] || '',
      small: datatype['小规模纳税人'] || '',
    }
    formulaDialogVisible.value = true
  }
}

function onDragStart(e, variable) {
  // 判断同名变量数量
  const sameDescCount = variables.value.filter(v => v.description === variable.description).length
  let text = ''
  if (sameDescCount === 1) {
    text = variable.description
  } else {
    text = variable.description + (variable.unit ? `(${variable.unit})` : '')
  }
  e.dataTransfer.setData('text/plain', text)
}

function onDrop(e) {
  e.preventDefault()
  const text = e.dataTransfer.getData('text/plain')
  const textarea = e.target
  const start = textarea.selectionStart
  const end = textarea.selectionEnd
  const currentValue = textarea.value
  const newValue = currentValue.substring(0, start) + text + currentValue.substring(end)

  // Update model based on ID
  const id = textarea.id
  if (id === 'consumption-cumpte') {
    consumptionCumpte.value = newValue
  } else if (id === 'vat-general-cumpte') {
    valueAddedCumpte.value.general = newValue
  } else if (id === 'vat-small-cumpte') {
    valueAddedCumpte.value.small = newValue
  }

  nextTick(() => {
    textarea.focus()
    textarea.selectionStart = textarea.selectionEnd = start + text.length
  })
}

function onDragOver(e) {
  e.preventDefault()
}

function convertToDatatype(cumpteFormula) {
  if (!cumpteFormula) return ''
  let result = cumpteFormula
  // 1. 先用 description+unit 替换
  Object.entries(variableMap.value)
    .sort((a, b) => b[0].length - a[0].length)
    .forEach(([descUnit, v]) => {
      result = result.replaceAll(descUnit, v)
    })
  // 2. 再用 description 替换（仅唯一时）
  // 收集所有 description 出现次数
  const descCount = {}
  variables.value.forEach(v => {
    descCount[v.description] = (descCount[v.description] || 0) + 1
  })
  variables.value.forEach(v => {
    if (descCount[v.description] === 1) {
      result = result.replaceAll(v.description, v.variable)
    }
  })
  // 百分号转小数（如 36% -> 0.36）
  result = result.replace(/(\d+(?:\.\d+)?)%/g, (_, num) => {
    return parseFloat(num) / 100
  })
  return result
}

function isFormulaValid(formula) {
  if (!formula) return true // 空公式视为合法
  try {
    // 替换变量为数字，百分号转小数
    let expr = convertToDatatype(formula)
    // 变量全部替换为1
    expr = expr.replace(/[a-zA-Z_][a-zA-Z0-9_]*/g, '1')
    // 尝试计算
    // eslint-disable-next-line no-new-func
    new Function('return ' + expr)()
    return true
  } catch (e) {
    return false
  }
}

// 新增：一键替换功能相关
// 通用替换函数
function replaceInFormula(formula, searchText, variableText) {
  if (!searchText) return formula
  // 全部替换，忽略大小写
  const reg = new RegExp(searchText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'gi')
  return formula.replace(reg, variableText)
}

// 新增：一键替换输入框和按钮绑定变量
const replaceFrom = ref('')
const replaceTo = ref('')

function handleReplaceInFormula() {
  if (!replaceFrom.value) {
    proxy.$modal.msgWarning('请输入要替换的内容')
    return
  }
  if (!replaceTo.value) {
    proxy.$modal.msgWarning('请输入目标变量')
    return
  }
  consumptionCumpte.value = replaceInFormula(consumptionCumpte.value, replaceFrom.value, replaceTo.value)
  valueAddedCumpte.value.general = replaceInFormula(valueAddedCumpte.value.general, replaceFrom.value, replaceTo.value)
  valueAddedCumpte.value.small = replaceInFormula(valueAddedCumpte.value.small, replaceFrom.value, replaceTo.value)
  proxy.$modal.msgSuccess('三个公式已全部替换')
}

watch(consumptionCumpte, (val) => {
  consumptionDatatype.value = convertToDatatype(val)
})
watch(() => valueAddedCumpte.value.general, (val) => {
  valueAddedDatatype.value.general = convertToDatatype(val)
})
watch(() => valueAddedCumpte.value.small, (val) => {
  valueAddedDatatype.value.small = convertToDatatype(val)
})

function saveFormulas() {
  // 校验消费税公式
  if (!isFormulaValid(consumptionCumpte.value)) {
    proxy.$modal.msgError('消费税公式不合法，请检查公式格式')
    return
  }
  // 校验增值税公式
  if (!isFormulaValid(valueAddedCumpte.value.general)) {
    proxy.$modal.msgError('增值税公式（一般纳税人）不合法，请检查公式格式')
    return
  }
  if (!isFormulaValid(valueAddedCumpte.value.small)) {
    proxy.$modal.msgError('增值税公式（小规模纳税人）不合法，请检查公式格式')
    return
  }

  if (!currentNode.value) return

  const dataToUpdate = { ...currentNode.value }
  dataToUpdate.consumptionCumpte = consumptionCumpte.value
  dataToUpdate.consumptionDataType = consumptionDatatype.value
  dataToUpdate.valueAddedRate = `{一般纳税人: '${valueAddedRate.value.general}', 小规模纳税人: '${valueAddedRate.value.small}'}`
  dataToUpdate.valueAddedCumpte = `{一般纳税人: '${valueAddedCumpte.value.general}', 小规模纳税人: '${valueAddedCumpte.value.small}'}`
  dataToUpdate.valueAddedDatatype = `{一般纳税人: '${valueAddedDatatype.value.general}', 小规模纳税人: '${valueAddedDatatype.value.small}'}`

  updateCategories(dataToUpdate).then(() => {
    proxy.$modal.msgSuccess('保存成功')
    formulaDialogVisible.value = false
    Object.assign(currentNode.value, dataToUpdate)
  })
}

onMounted(() => {
  getCategoriesTree()
  getVariables()
})
</script>

<template>
  <div>
    <el-tree
      v-loading="loading"
      :data="categoriesTree"
      :props="treeProps"
      node-key="id"
      default-expand-all
      highlight-current
      style="width: 100%;"
      @node-click="handleNodeClick"
    />
    <el-dialog v-model="formulaDialogVisible" width="800px" append-to-body>
      <template #header>
        <div style="display: flex; align-items: center; justify-content: space-between; width: 100%;">
          <span>公式设计</span>
          <div style="display: flex; align-items: center; gap: 8px;">
            <el-input v-model="replaceFrom" size="small" placeholder="要替换内容" style="width: 120px;" />
            <span>替换</span>
            <el-input v-model="replaceTo" size="small" placeholder="目标变量" style="width: 120px;" />
            <el-button size="small" type="primary" @click="handleReplaceInFormula">替换</el-button>
          </div>
        </div>
      </template>
      <div style="display: flex; gap: 16px;">
        <div style="width: 230px;">
          <div style="font-weight: bold; margin-bottom: 8px;">可用变量</div>
          <div v-for="v in variables" :key="v.variable"
            draggable="true"
            @dragstart="e => onDragStart(e, v)"
            @click="onVariableClick(v)"
            style="padding: 4px 8px; margin-bottom: 4px; background: #f5f7fa; border: 1px solid #dcdfe6; border-radius: 4px; cursor: pointer;">
            <span style="color: #409EFF; font-weight: bold;">{{ v.variable }}</span>：{{ v.description }}<span v-if="v.unit"> ({{ v.unit }})</span>
          </div>
        </div>
        <div style="flex: 1;">
          <el-tabs>
            <el-tab-pane label="消费税公式">
              <el-row :gutter="20">
                <el-col :span="24">
                  <el-form label-position="top">
                    <el-form-item label="税率">
                      <el-input :value="currentNode.consumptionRate" disabled />
                    </el-form-item>
                  </el-form>
                </el-col>
              </el-row>
              <div style="font-weight: bold; margin-bottom: 8px; display: flex; align-items: center;">
                计算公式
              </div>
              <el-input
                id="consumption-cumpte"
                v-model="consumptionCumpte"
                type="textarea"
                :rows="4"
                placeholder="请输入消费税计算公式"
                @drop.prevent="onDrop"
                @dragover.prevent="onDragOver"
                @focus="onTextareaFocus"
                style="margin-bottom: 8px;"
              />
              <div style="font-size: 13px; color: #888; margin-bottom: 8px;">变量表达式</div>
              <el-input
                v-model="consumptionDatatype"
                type="textarea"
                :rows="2"
                readonly
                disabled
                style="background: #f5f7fa;"
              />
            </el-tab-pane>
            <el-tab-pane label="增值税公式">
              <el-row :gutter="20">
                <el-col :span="12">
                  <div style="font-weight: bold; margin-bottom: 8px;">一般纳税人</div>
                  <el-form label-position="top">
                    <el-form-item label="税率">
                      <el-input :value="valueAddedRate.general" disabled />
                    </el-form-item>
                    <el-form-item label="计算公式">
                      <el-input id="vat-general-cumpte" type="textarea" :rows="4" v-model="valueAddedCumpte.general" @drop.prevent="onDrop" @dragover.prevent="onDragOver" @focus="onTextareaFocus" />
                    </el-form-item>
                    <el-form-item label="变量表达式">
                      <el-input type="textarea" :rows="2" v-model="valueAddedDatatype.general" readonly disabled style="background: #f5f7fa;" />
                    </el-form-item>
                  </el-form>
                </el-col>
                <el-col :span="12">
                  <div style="font-weight: bold; margin-bottom: 8px;">小规模纳税人</div>
                  <el-form label-position="top">
                    <el-form-item label="税率">
                      <el-input :value="valueAddedRate.small" disabled />
                    </el-form-item>
                    <el-form-item label="计算公式">
                      <el-input id="vat-small-cumpte" type="textarea" :rows="4" v-model="valueAddedCumpte.small" @drop.prevent="onDrop" @dragover.prevent="onDragOver" @focus="onTextareaFocus" />
                    </el-form-item>
                    <el-form-item label="变量表达式">
                      <el-input type="textarea" :rows="2" v-model="valueAddedDatatype.small" readonly disabled style="background: #f5f7fa;" />
                    </el-form-item>
                  </el-form>
                </el-col>
              </el-row>
            </el-tab-pane>
          </el-tabs>
        </div>
      </div>
      <template #footer>
        <el-button @click="formulaDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="saveFormulas">保存</el-button>
      </template>
    </el-dialog>
  </div>
</template>